Examples

Notebooks

In the folder notebooks several notebooks, using Pluto.jl, for the simulation of GC-systems are available.

To use these notebooks Julia, v1.6 or above, must be installed and Pluto must be added:

julia> ]
(v1.7) pkg> add Pluto

To run Pluto, use the following commands:

julia> using Pluto
julia> Pluto.run()

Pluto will open your browser. In the field Open from file the URL of a notebook or the path to a locally downloaded notebook can be insert and the notebook will open and load the necessary packages.

Overview of notebooks

  • simulation_conventional_GC.jl - simulation of a conventional GC-system (constant temperature, constant diameter and constant film thickness along the column) and outlet pressure as "vacuum" or "atmospheric", now with option of flow or pressure control and temperature program notation in the typical form used in commercial GC software (temperature levels, holding times and heating ramps)
  • simulation_conventional_GC_load_2dbs.jl - simulation of a conventional GC-system (constant temperature, constant diameter and constant film thickness along the column) and loading of up to two different substance databases and simulation of the common substances with the same GC-system and comparing the result. Also, an option is given, to load measured retention times and compare these to the simulations. Same setting for programs as in simulation_conventional_GC.jl
  • simulation_example.jl - general example of simulation of a GC-system with optional thermal gradient (exponential/linear model of temperature change along the column) and constant diameter and constant film thickness along the column.
  • simulation_example_input_gradient_function.jl - simulation of a GC-system with optional thermal gradient where the temperature change along the column is defined by a user-defined equation (cosine-function as example)

Simulation of measurements

Two measurements from [8] will be simulated and compared to the measured chromatograms. The n-alkanes from n-nonane (C9) to n-triacontane (C30) are separated in a conventional GC and a thermal gradient GC . The database with the thermodynamic parameters is Database_Leppert2020b.csv.

Conventional GC

The conventional GC program simulated here is Prog. D from [8], a temperature program with two heating ramps, constant inlet pressure and a flame ionization detector (FID, atmospheric outlet pressure).

The standard options are used. Only the option ng (non-gradient) is changed to true. Because the conventional GC does not use non-uniform temperature, diameter or film thickness, the model can be simplified and the calculation of the separation is faster.

opt = GasChromatographySimulator.Options(ng=true)
GasChromatographySimulator.Options(OwrenZen5(), 1.0e-6, 0.001, "inlet", true, true, "Blumberg", "Pressure")

The column is defined as:

col = GasChromatographySimulator.Column(11.18, 0.104e-3, 0.104e-6, "FS5ms", "H2")
GasChromatographySimulator.Column(11.18, 0.000104, [0.000104], 1.04e-7, [1.04e-7], "FS5ms", "H2")

The program is defined as:

prog_D = GasChromatographySimulator.Program([0.0, 60.0, 1680.0, 60.0, 360.0, 60.0], [40.0, 40.0, 180.0, 180.0, 300.0, 300.0], 411564.0*ones(6), 101300.0.*ones(6), col.L)
GasChromatographySimulator.Program{GasChromatographySimulator.var"#gf#5"{Matrix{Float64}}}([0.0, 60.0, 1680.0, 60.0, 360.0, 60.0], [40.0, 40.0, 180.0, 180.0, 300.0, 300.0], [411564.0, 411564.0, 411564.0, 411564.0, 411564.0, 411564.0], [101300.0, 101300.0, 101300.0, 101300.0, 101300.0, 101300.0], GasChromatographySimulator.var"#gf#5"{Matrix{Float64}}([0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0; … ; 0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0]), [0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0; … ; 0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0], 11181×6 extrapolate(interpolate((0.0:0.001:11.18,::Vector{Float64}), ::Matrix{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
   ⋮                                       ⋮
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15, 6-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 411564.0
 411564.0
 411564.0
 411564.0
 411564.0
 411564.0, 6-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 101300.0
 101300.0
 101300.0
 101300.0
 101300.0
 101300.0)

We want to use all solutes for the stationary phase FS5ms, which are in the database. We load the database into a dataframe:

db_dataframe = DataFrame(CSV.File("../../data/Database_Leppert2020b.csv", header=1, silencewarnings=true))

22 rows × 11 columns

NameCASPhaseTcharthetacharDeltaCpphi0SourceCat_1Cat_2Cat_3
String3String15String7Float64Float64Float64Float64String15String7String7String7
1C9111-84-2FS5ms98.0430.1789.340.001Leppert2020balkanealkanesmissing
2C10124-18-5FS5ms118.0932.24112.490.001Leppert2020balkaneGrobalkanes
3C111120-21-4FS5ms137.0733.71116.040.001Leppert2020balkaneGrobalkanes
4C12112-40-3FS5ms154.7834.92121.440.001Leppert2020balkanealkanesmissing
5C13629-50-5FS5ms171.3235.93125.620.001Leppert2020balkanealkanesmissing
6C14629-59-4FS5ms186.8336.76126.760.001Leppert2020balkanealkanesmissing
7C15629-62-9FS5ms201.2537.39129.620.001Leppert2020balkanealkanesmissing
8C16544-76-3FS5ms215.138.46142.180.001Leppert2020balkanealkanesmissing
9C17629-78-7FS5ms227.9138.95145.360.001Leppert2020balkanealkanesmissing
10C18593-45-3FS5ms240.139.58153.290.001Leppert2020balkanealkanesmissing
11C19629-92-5FS5ms251.840.21159.470.001Leppert2020balkanealkanesmissing
12C20112-95-8FS5ms262.8140.67164.990.001Leppert2020balkanealkanesmissing
13C21629-94-7FS5ms273.3941.43179.470.001Leppert2020balkanealkanesmissing
14C22629-97-0FS5ms283.5541.89183.350.001Leppert2020balkanealkanesmissing
15C23638-67-5FS5ms293.1142.25188.990.001Leppert2020balkanealkanesmissing
16C24646-31-1FS5ms302.0542.21188.530.001Leppert2020balkanealkanesmissing
17C25629-99-2FS5ms310.6742.26189.510.001Leppert2020balkanealkanesmissing
18C26630-1-3FS5ms320.4244.16216.770.001Leppert2020balkanemissingmissing
19C27593-49-7FS5ms326.6241.9184.170.001Leppert2020balkanealkanesmissing
20C28630-2-4FS5ms334.1941.82183.910.001Leppert2020balkanemissingmissing
21C29630-3-5FS5ms341.441.67183.070.001Leppert2020balkanemissingmissing
22C30638-68-6FS5ms348.3941.57183.280.001Leppert2020balkanealkanesmissing

and extract all the names of the substances with:

solutes = GasChromatographySimulator.all_solutes(col.sp, db_dataframe)
22-element Vector{String}:
 "C9"
 "C10"
 "C11"
 "C12"
 "C13"
 "C14"
 "C15"
 "C16"
 "C17"
 "C18"
 ⋮
 "C22"
 "C23"
 "C24"
 "C25"
 "C26"
 "C27"
 "C28"
 "C29"
 "C30"

The data for all solutes is finally loaded with:

t₀ = zeros(length(solutes))
τ₀ = zeros(length(solutes))
sub = GasChromatographySimulator.load_solute_database(db_dataframe, col.sp, col.gas, solutes, t₀, τ₀)
22-element Vector{GasChromatographySimulator.Substance}:
 GasChromatographySimulator.Substance("C9", "111-84-2", 371.19, 30.17, 89.34, 0.001, "Leppert2020b, alkane, alkanes", 0.0001253206335721764, 0.0, 0.0)
 GasChromatographySimulator.Substance("C10", "124-18-5", 391.24, 32.24, 112.49, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011884991852543487, 0.0, 0.0)
 GasChromatographySimulator.Substance("C11", "1120-21-4", 410.21999999999997, 33.71, 116.04, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011323854999018596, 0.0, 0.0)
 GasChromatographySimulator.Substance("C12", "112-40-3", 427.92999999999995, 34.92, 121.44, 0.001, "Leppert2020b, alkane, alkanes", 0.00010831148421185742, 0.0, 0.0)
 GasChromatographySimulator.Substance("C13", "629-50-5", 444.46999999999997, 35.93, 125.62, 0.001, "Leppert2020b, alkane, alkanes", 0.00010393999972322901, 0.0, 0.0)
 GasChromatographySimulator.Substance("C14", "629-59-4", 459.98, 36.76, 126.76, 0.001, "Leppert2020b, alkane, alkanes", 0.00010002700149772162, 0.0, 0.0)
 GasChromatographySimulator.Substance("C15", "629-62-9", 474.4, 37.39, 129.62, 0.001, "Leppert2020b, alkane, alkanes", 9.64976601701651e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C16", "544-76-3", 488.25, 38.46, 142.18, 0.001, "Leppert2020b, alkane, alkanes", 9.329323536538124e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C17", "629-78-7", 501.05999999999995, 38.95, 145.36, 0.001, "Leppert2020b, alkane, alkanes", 9.036687565381776e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C18", "593-45-3", 513.25, 39.58, 153.29, 0.001, "Leppert2020b, alkane, alkanes", 8.768068754143736e-5, 0.0, 0.0)
 ⋮
 GasChromatographySimulator.Substance("C22", "629-97-0", 556.7, 41.89, 183.35, 0.001, "Leppert2020b, alkane, alkanes", 7.879073502414208e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C23", "638-67-5", 566.26, 42.25, 188.99, 0.001, "Leppert2020b, alkane, alkanes", 7.693149436827684e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C24", "646-31-1", 575.2, 42.21, 188.53, 0.001, "Leppert2020b, alkane, alkanes", 7.518755251713027e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C25", "629-99-2", 583.8199999999999, 42.26, 189.51, 0.001, "Leppert2020b, alkane, alkanes", 7.354754525382887e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C26", "630-1-3", 593.5699999999999, 44.16, 216.77, 0.001, "Leppert2020b, alkane", 7.200161658208628e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C27", "593-49-7", 599.77, 41.9, 184.17, 0.001, "Leppert2020b, alkane, alkanes", 7.054117055654164e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C28", "630-2-4", 607.3399999999999, 41.82, 183.91, 0.001, "Leppert2020b, alkane", 6.915867131183108e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C29", "630-3-5", 614.55, 41.67, 183.07, 0.001, "Leppert2020b, alkane", 6.784748059430345e-5, 0.0, 0.0)
 GasChromatographySimulator.Substance("C30", "638-68-6", 621.54, 41.57, 183.28, 0.001, "Leppert2020b, alkane, alkanes", 6.660172475097402e-5, 0.0, 0.0)

The injection is assumed to be ideal with initial peak widths τ₀ of 0 seconds and occuring at the beginning of the temperature program (t₀ of 0 seconds).

The parameters are combined:

par = GasChromatographySimulator.Parameters(col, prog_D, sub, opt)
GasChromatographySimulator.Parameters(GasChromatographySimulator.Column(11.18, 0.000104, [0.000104], 1.04e-7, [1.04e-7], "FS5ms", "H2"), GasChromatographySimulator.Program{GasChromatographySimulator.var"#gf#5"{Matrix{Float64}}}([0.0, 60.0, 1680.0, 60.0, 360.0, 60.0], [40.0, 40.0, 180.0, 180.0, 300.0, 300.0], [411564.0, 411564.0, 411564.0, 411564.0, 411564.0, 411564.0], [101300.0, 101300.0, 101300.0, 101300.0, 101300.0, 101300.0], GasChromatographySimulator.var"#gf#5"{Matrix{Float64}}([0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0; … ; 0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0]), [0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0; … ; 0.0 0.0 11.18 0.0; 0.0 0.0 11.18 0.0], 11181×6 extrapolate(interpolate((0.0:0.001:11.18,::Vector{Float64}), ::Matrix{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
   ⋮                                       ⋮
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15
 313.15  313.15  453.15  453.15  573.15  573.15, 6-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 411564.0
 411564.0
 411564.0
 411564.0
 411564.0
 411564.0, 6-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 101300.0
 101300.0
 101300.0
 101300.0
 101300.0
 101300.0), GasChromatographySimulator.Substance[GasChromatographySimulator.Substance("C9", "111-84-2", 371.19, 30.17, 89.34, 0.001, "Leppert2020b, alkane, alkanes", 0.0001253206335721764, 0.0, 0.0), GasChromatographySimulator.Substance("C10", "124-18-5", 391.24, 32.24, 112.49, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011884991852543487, 0.0, 0.0), GasChromatographySimulator.Substance("C11", "1120-21-4", 410.21999999999997, 33.71, 116.04, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011323854999018596, 0.0, 0.0), GasChromatographySimulator.Substance("C12", "112-40-3", 427.92999999999995, 34.92, 121.44, 0.001, "Leppert2020b, alkane, alkanes", 0.00010831148421185742, 0.0, 0.0), GasChromatographySimulator.Substance("C13", "629-50-5", 444.46999999999997, 35.93, 125.62, 0.001, "Leppert2020b, alkane, alkanes", 0.00010393999972322901, 0.0, 0.0), GasChromatographySimulator.Substance("C14", "629-59-4", 459.98, 36.76, 126.76, 0.001, "Leppert2020b, alkane, alkanes", 0.00010002700149772162, 0.0, 0.0), GasChromatographySimulator.Substance("C15", "629-62-9", 474.4, 37.39, 129.62, 0.001, "Leppert2020b, alkane, alkanes", 9.64976601701651e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C16", "544-76-3", 488.25, 38.46, 142.18, 0.001, "Leppert2020b, alkane, alkanes", 9.329323536538124e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C17", "629-78-7", 501.05999999999995, 38.95, 145.36, 0.001, "Leppert2020b, alkane, alkanes", 9.036687565381776e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C18", "593-45-3", 513.25, 39.58, 153.29, 0.001, "Leppert2020b, alkane, alkanes", 8.768068754143736e-5, 0.0, 0.0)  …  GasChromatographySimulator.Substance("C21", "629-94-7", 546.54, 41.43, 179.47, 0.001, "Leppert2020b, alkane, alkanes", 8.077845767414391e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C22", "629-97-0", 556.7, 41.89, 183.35, 0.001, "Leppert2020b, alkane, alkanes", 7.879073502414208e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C23", "638-67-5", 566.26, 42.25, 188.99, 0.001, "Leppert2020b, alkane, alkanes", 7.693149436827684e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C24", "646-31-1", 575.2, 42.21, 188.53, 0.001, "Leppert2020b, alkane, alkanes", 7.518755251713027e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C25", "629-99-2", 583.8199999999999, 42.26, 189.51, 0.001, "Leppert2020b, alkane, alkanes", 7.354754525382887e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C26", "630-1-3", 593.5699999999999, 44.16, 216.77, 0.001, "Leppert2020b, alkane", 7.200161658208628e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C27", "593-49-7", 599.77, 41.9, 184.17, 0.001, "Leppert2020b, alkane, alkanes", 7.054117055654164e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C28", "630-2-4", 607.3399999999999, 41.82, 183.91, 0.001, "Leppert2020b, alkane", 6.915867131183108e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C29", "630-3-5", 614.55, 41.67, 183.07, 0.001, "Leppert2020b, alkane", 6.784748059430345e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C30", "638-68-6", 621.54, 41.57, 183.28, 0.001, "Leppert2020b, alkane, alkanes", 6.660172475097402e-5, 0.0, 0.0)], GasChromatographySimulator.Options(OwrenZen5(), 1.0e-6, 0.001, "inlet", true, true, "Blumberg", "Pressure"))

The temperature program and the pressure/flow program can be plotted:

p_flow = GasChromatographySimulator.plot_flow(par)
p_press = GasChromatographySimulator.plot_pressure(par)
p_temp = GasChromatographySimulator.plot_temperature(par)
l = @layout([a{0.65w} [b; c]])
p_TpF = plot(p_temp, p_press, p_flow, layout=l)

And the simulation is run:

peaklist, sol = GasChromatographySimulator.simulate(par)
peaklist

22 rows × 9 columns

NametRτRTRσRuRkRResΔs
StringFloat64Float64Float64Float64Float64Float64Float64Float64
1C9140.7360.38936546.7280.1080430.2774858.1549462.0615251.3
2C10260.0670.57203556.67230.1110850.19419311.807760.3035241.968
3C11412.80.69433469.40.1115290.16062814.083857.6982230.933
4C12580.1760.75610683.3480.1106970.14640515.098354.1223216.517
5C13747.1110.78609897.25930.10940.13916815.492250.2939201.185
6C14907.1190.804631110.5930.1080690.13430915.674947.6137190.458
7C151061.40.815528123.450.1067950.13095215.715745.0212180.085
8C161208.710.820451135.7260.1056290.12874515.646242.3496169.4
9C171348.330.827944147.3610.1046520.126415.627640.2379160.952
10C181481.960.832643158.4970.1037870.12464815.557537.8877151.551
11C191608.620.838851169.0520.1030620.12286115.518336.125144.5
12C201730.230.844286179.1860.1024290.1213215.466240.1499161.572
13C211849.80.644716196.5990.1027310.15934311.211330.4644123.538
14C221915.210.428977218.4050.1016670.2369986.9541329.0921116.678
15C231961.050.358729233.6820.1008260.2810645.5651327.037108.237
16C241998.010.324749246.0020.09943350.3061864.9260825.2133100.886
17C252029.760.305047256.5880.09780420.320624.5798723.879395.5247
18C262058.460.295771266.1530.09718760.3285914.376722.199488.7995
19C272084.510.291112274.8380.09696980.3331024.2448121.197184.7895
20C282109.060.287879283.020.09654870.3353794.1553320.180380.7212
21C292132.240.286462290.7470.09636380.3363934.0902619.309877.2394
22C302154.340.285686298.1120.09615420.3365734.04139NaNNaN

The file Leppert2020b_measured_RT_progD.csv contains the retention times and peak widths (as standard deviations) from the measured chromatogram.

measurement_D = DataFrame(CSV.File("../../data/measurements/Leppert2020b_measured_RT_progD.csv", header=1, silencewarnings=true))
measurement_D[!, 2] = measurement_D[!, 2] .* 60.0 # conversion from min -> s
rename!(measurement_D, [:Name, :tR, :τR])

22 rows × 3 columns

NametRτR
String3Float64Float64
1C9151.020.452
2C10273.540.654
3C11428.880.801
4C12596.280.872
5C13763.080.918
6C14923.880.926
7C151077.240.944
8C161223.220.936
9C171362.060.94
10C181494.180.951
11C191620.360.956
12C201741.080.988
13C211853.280.657
14C221914.180.466
15C231958.040.391
16C241993.920.38
17C252025.180.343
18C262053.440.333
19C272079.420.327
20C282103.90.311
21C292127.00.318
22C302149.20.306

The simulated and measured separations can be compared by comparing the peak lists:

compare = GasChromatographySimulator.compare_peaklist(measurement_D, peaklist)

22 rows × 9 columns

NametR1tR2ΔtRrel_tRτR1τR2ΔτRrel_τR
String3Float64Float64Float64Float64Float64Float64Float64Float64
1C9151.02140.73610.28456.810020.4520.3893650.062635513.8574
2C10273.54260.06713.47284.925340.6540.5720350.081964712.5328
3C11428.88412.816.07973.749230.8010.6943340.10666613.3166
4C12596.28580.17616.10412.700770.8720.7561060.11589413.2906
5C13763.08747.11115.96882.092680.9180.7860980.13190214.3684
6C14923.88907.11916.7611.81420.9260.8046310.12136913.1068
7C151077.241061.415.83751.470190.9440.8155280.12847213.6094
8C161223.221208.7114.511.186220.9360.8204510.11554912.345
9C171362.061348.3313.73231.00820.940.8279440.11205611.9209
10C181494.181481.9612.21530.8175280.9510.8326430.11835712.4456
11C191620.361608.6211.73730.7243660.9560.8388510.11714912.254
12C201741.081730.2310.85070.6232170.9880.8442860.14371414.546
13C211853.281849.83.484190.1880010.6570.6447160.01228391.8697
14C221914.181915.21-1.03465-0.05405180.4660.4289770.03702277.94478
15C231958.041961.05-3.00671-0.1535570.3910.3587290.03227118.25348
16C241993.921998.01-4.08506-0.2048760.380.3247490.05525114.5397
17C252025.182029.76-4.5835-0.2263260.3430.3050470.03795311.065
18C262053.442058.46-5.01769-0.2443560.3330.2957710.037228911.1798
19C272079.422084.51-5.09458-0.2450.3270.2911120.035888410.975
20C282103.92109.06-5.16049-0.2452820.3110.2878790.02312087.43435
21C292127.02132.24-5.24121-0.2464130.3180.2864620.03153799.91757
22C302149.22154.34-5.13739-0.2390370.3060.2856860.02031416.63858

or by comparing the chromatograms:

chrom_D = DataFrame(CSV.File("../../data/measurements/Leppert2020b_measured_Chrom_progD.csv", header=1, silencewarnings=true))
p_chrom, t, chrom = GasChromatographySimulator.plot_chromatogram(peaklist, (0.0, round(chrom_D[end,1];sigdigits=2)); annotation=false, number=true, mirror=true, offset=0.0)
plot!(p_chrom, chrom_D[!,1], chrom_D[!,2].*400.0.+0.1)
ylims!(-1.6,1.6)
xlims!(0.0,round(chrom_D[end,1];sigdigits=2))
p_chrom

Thermal gradient GC

The following example of a thermal gradient GC is the example medium gradient from [8].

Standard options are used:

opt_tg = GasChromatographySimulator.Options()
GasChromatographySimulator.Options(OwrenZen5(), 1.0e-6, 0.001, "inlet", true, false, "Blumberg", "Pressure")

And the column is defined as:

col_tg = GasChromatographySimulator.Column(2.05, 0.104e-3, 0.104e-6, "FS5ms", "He")
GasChromatographySimulator.Column(2.05, 0.000104, [0.000104], 1.04e-7, [1.04e-7], "FS5ms", "He")

The program is taken from the measured temperatures and pressures during the GC run, stored in the file Leppert2020b_prog_settings_med_gradient_x90.csv:

prog_settings = DataFrame(CSV.File("../../data/measurements/Leppert2020b_prog_settings_med_gradient_x90.csv", header=1, silencewarnings=true))
# use only every 20th measurement
time = cumsum(prog_settings.Deltat)[1:20:end]
time_steps = Array{Float64}(undef, length(time))
for i=2:length(time)
    time_steps[i] = time[i]-time[i-1]
end
time_steps[1] = 0.0
temp_steps = prog_settings.T[1:20:end]
ΔT_steps = prog_settings.DeltaT[1:20:end]
pin_steps = prog_settings.pinj[1:20:end].*1000.0 .+ 101300.0
pout_steps = prog_settings.pdet[1:20:end].*1000.0
α_steps = -3.0.*ones(length(ΔT_steps))
x₀_steps = zeros(length(ΔT_steps))
L₀_steps = col_tg.L.*ones(length(ΔT_steps))
prog_med_grad = GasChromatographySimulator.Program(time_steps, temp_steps, pin_steps, pout_steps, ΔT_steps, x₀_steps, L₀_steps, α_steps, "outlet", col_tg.L)
GasChromatographySimulator.Program{GasChromatographySimulator.var"#gf#2"{String, Matrix{Float64}}}([0.0, 0.9200000000000003, 0.9100000000000007, 0.9199999999999986, 0.9199999999999995, 0.910000000000001, 0.9199999999999999, 0.9199999999999982, 0.9200000000000008, 0.9300000000000006  …  0.9199999999999875, 0.9100000000000108, 0.9200000000000017, 0.9099999999999966, 0.9200000000000017, 0.9099999999999966, 0.9200000000000017, 0.9099999999999966, 0.9099999999999966, 0.9200000000000017], [49.323, 48.954, 49.323, 49.077, 49.569, 49.446, 48.831, 49.323, 49.077, 49.077  …  63.099, 56.211, 51.414, 48.339, 46.74, 45.51, 44.895, 44.28, 43.911, 43.542], [354589.48, 354562.67000000004, 354589.48, 354571.61, 354607.32, 354598.4, 354553.72, 354589.48, 354571.61, 354571.61  …  355560.34, 355082.14, 354740.58, 354517.9, 354400.94, 354310.42000000004, 354264.98, 354219.43, 354192.04000000004, 354164.6], [230168.87, 230224.3, 230168.87, 230205.81999999998, 230131.96, 230150.41, 230242.79, 230168.87, 230205.81999999998, 230205.81999999998  …  228154.50999999998, 229148.40000000002, 229856.25, 230316.84999999998, 230558.51, 230745.38999999998, 230839.16, 230933.15000000002, 230989.65000000002, 231046.23], GasChromatographySimulator.var"#gf#2"{String, Matrix{Float64}}("outlet", [-2.829 0.0 2.05 -3.0; -2.46 0.0 2.05 -3.0; … ; -1.23 0.0 2.05 -3.0; -0.984 0.0 2.05 -3.0]), [-2.829 0.0 2.05 -3.0; -2.46 0.0 2.05 -3.0; … ; -1.23 0.0 2.05 -3.0; -0.984 0.0 2.05 -3.0], 2051×108 extrapolate(interpolate((0.0:0.001:2.05,::Vector{Float64}), ::Matrix{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 319.644  319.644  319.644  319.89   …  316.077  315.954  315.831  315.708
 319.644  319.644  319.644  319.89      316.077  315.954  315.831  315.708
 319.645  319.644  319.645  319.89      316.077  315.954  315.831  315.708
 319.645  319.645  319.645  319.891     316.078  315.954  315.831  315.708
 319.645  319.645  319.645  319.891     316.078  315.955  315.831  315.708
 319.645  319.645  319.645  319.891  …  316.078  315.955  315.832  315.708
 319.646  319.645  319.646  319.891     316.078  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.078  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.079  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.079  315.955  315.832  315.709
   ⋮                                 ⋱             ⋮               
 322.44   322.075  322.44   322.199     318.022  317.413  317.046  316.68
 322.444  322.079  322.444  322.203     318.025  317.415  317.048  316.682
 322.448  322.082  322.448  322.206     318.028  317.417  317.05   316.683
 322.452  322.086  322.452  322.21   …  318.03   317.419  317.052  316.685
 322.456  322.089  322.456  322.213     318.033  317.421  317.054  316.686
 322.46   322.093  322.46   322.217     318.036  317.423  317.056  316.688
 322.465  322.097  322.465  322.22      318.039  317.426  317.057  316.689
 322.469  322.1    322.469  322.224     318.042  317.428  317.059  316.691
 322.473  322.104  322.473  322.227  …  318.045  317.43   317.061  316.692, 108-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 354589.48
 354562.67000000004
 354589.48
 354571.61
 354607.32
 354598.4
 354553.72
 354589.48
 354571.61
 354571.61
      ⋮
 355082.14
 354740.58
 354517.9
 354400.94
 354310.42000000004
 354264.98
 354219.43
 354192.04000000004
 354164.6, 108-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 230168.87
 230224.3
 230168.87
 230205.81999999998
 230131.96
 230150.41
 230242.79
 230168.87
 230205.81999999998
 230205.81999999998
      ⋮
 229148.40000000002
 229856.25
 230316.84999999998
 230558.51
 230745.38999999998
 230839.16
 230933.15000000002
 230989.65000000002
 231046.23)

The same solutes are used as in the previous example.

The parameters are combined:

par_tg = GasChromatographySimulator.Parameters(col_tg, prog_med_grad, sub, opt_tg)
GasChromatographySimulator.Parameters(GasChromatographySimulator.Column(2.05, 0.000104, [0.000104], 1.04e-7, [1.04e-7], "FS5ms", "He"), GasChromatographySimulator.Program{GasChromatographySimulator.var"#gf#2"{String, Matrix{Float64}}}([0.0, 0.9200000000000003, 0.9100000000000007, 0.9199999999999986, 0.9199999999999995, 0.910000000000001, 0.9199999999999999, 0.9199999999999982, 0.9200000000000008, 0.9300000000000006  …  0.9199999999999875, 0.9100000000000108, 0.9200000000000017, 0.9099999999999966, 0.9200000000000017, 0.9099999999999966, 0.9200000000000017, 0.9099999999999966, 0.9099999999999966, 0.9200000000000017], [49.323, 48.954, 49.323, 49.077, 49.569, 49.446, 48.831, 49.323, 49.077, 49.077  …  63.099, 56.211, 51.414, 48.339, 46.74, 45.51, 44.895, 44.28, 43.911, 43.542], [354589.48, 354562.67000000004, 354589.48, 354571.61, 354607.32, 354598.4, 354553.72, 354589.48, 354571.61, 354571.61  …  355560.34, 355082.14, 354740.58, 354517.9, 354400.94, 354310.42000000004, 354264.98, 354219.43, 354192.04000000004, 354164.6], [230168.87, 230224.3, 230168.87, 230205.81999999998, 230131.96, 230150.41, 230242.79, 230168.87, 230205.81999999998, 230205.81999999998  …  228154.50999999998, 229148.40000000002, 229856.25, 230316.84999999998, 230558.51, 230745.38999999998, 230839.16, 230933.15000000002, 230989.65000000002, 231046.23], GasChromatographySimulator.var"#gf#2"{String, Matrix{Float64}}("outlet", [-2.829 0.0 2.05 -3.0; -2.46 0.0 2.05 -3.0; … ; -1.23 0.0 2.05 -3.0; -0.984 0.0 2.05 -3.0]), [-2.829 0.0 2.05 -3.0; -2.46 0.0 2.05 -3.0; … ; -1.23 0.0 2.05 -3.0; -0.984 0.0 2.05 -3.0], 2051×108 extrapolate(interpolate((0.0:0.001:2.05,::Vector{Float64}), ::Matrix{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 319.644  319.644  319.644  319.89   …  316.077  315.954  315.831  315.708
 319.644  319.644  319.644  319.89      316.077  315.954  315.831  315.708
 319.645  319.644  319.645  319.89      316.077  315.954  315.831  315.708
 319.645  319.645  319.645  319.891     316.078  315.954  315.831  315.708
 319.645  319.645  319.645  319.891     316.078  315.955  315.831  315.708
 319.645  319.645  319.645  319.891  …  316.078  315.955  315.832  315.708
 319.646  319.645  319.646  319.891     316.078  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.078  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.079  315.955  315.832  315.709
 319.646  319.646  319.646  319.892     316.079  315.955  315.832  315.709
   ⋮                                 ⋱             ⋮               
 322.44   322.075  322.44   322.199     318.022  317.413  317.046  316.68
 322.444  322.079  322.444  322.203     318.025  317.415  317.048  316.682
 322.448  322.082  322.448  322.206     318.028  317.417  317.05   316.683
 322.452  322.086  322.452  322.21   …  318.03   317.419  317.052  316.685
 322.456  322.089  322.456  322.213     318.033  317.421  317.054  316.686
 322.46   322.093  322.46   322.217     318.036  317.423  317.056  316.688
 322.465  322.097  322.465  322.22      318.039  317.426  317.057  316.689
 322.469  322.1    322.469  322.224     318.042  317.428  317.059  316.691
 322.473  322.104  322.473  322.227  …  318.045  317.43   317.061  316.692, 108-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 354589.48
 354562.67000000004
 354589.48
 354571.61
 354607.32
 354598.4
 354553.72
 354589.48
 354571.61
 354571.61
      ⋮
 355082.14
 354740.58
 354517.9
 354400.94
 354310.42000000004
 354264.98
 354219.43
 354192.04000000004
 354164.6, 108-element extrapolate(interpolate((::Vector{Float64},), ::Vector{Float64}, Gridded(Linear())), Flat()) with element type Float64:
 230168.87
 230224.3
 230168.87
 230205.81999999998
 230131.96
 230150.41
 230242.79
 230168.87
 230205.81999999998
 230205.81999999998
      ⋮
 229148.40000000002
 229856.25
 230316.84999999998
 230558.51
 230745.38999999998
 230839.16
 230933.15000000002
 230989.65000000002
 231046.23), GasChromatographySimulator.Substance[GasChromatographySimulator.Substance("C9", "111-84-2", 371.19, 30.17, 89.34, 0.001, "Leppert2020b, alkane, alkanes", 0.0001253206335721764, 0.0, 0.0), GasChromatographySimulator.Substance("C10", "124-18-5", 391.24, 32.24, 112.49, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011884991852543487, 0.0, 0.0), GasChromatographySimulator.Substance("C11", "1120-21-4", 410.21999999999997, 33.71, 116.04, 0.001, "Leppert2020b, alkane, Grob, alkanes", 0.00011323854999018596, 0.0, 0.0), GasChromatographySimulator.Substance("C12", "112-40-3", 427.92999999999995, 34.92, 121.44, 0.001, "Leppert2020b, alkane, alkanes", 0.00010831148421185742, 0.0, 0.0), GasChromatographySimulator.Substance("C13", "629-50-5", 444.46999999999997, 35.93, 125.62, 0.001, "Leppert2020b, alkane, alkanes", 0.00010393999972322901, 0.0, 0.0), GasChromatographySimulator.Substance("C14", "629-59-4", 459.98, 36.76, 126.76, 0.001, "Leppert2020b, alkane, alkanes", 0.00010002700149772162, 0.0, 0.0), GasChromatographySimulator.Substance("C15", "629-62-9", 474.4, 37.39, 129.62, 0.001, "Leppert2020b, alkane, alkanes", 9.64976601701651e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C16", "544-76-3", 488.25, 38.46, 142.18, 0.001, "Leppert2020b, alkane, alkanes", 9.329323536538124e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C17", "629-78-7", 501.05999999999995, 38.95, 145.36, 0.001, "Leppert2020b, alkane, alkanes", 9.036687565381776e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C18", "593-45-3", 513.25, 39.58, 153.29, 0.001, "Leppert2020b, alkane, alkanes", 8.768068754143736e-5, 0.0, 0.0)  …  GasChromatographySimulator.Substance("C21", "629-94-7", 546.54, 41.43, 179.47, 0.001, "Leppert2020b, alkane, alkanes", 8.077845767414391e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C22", "629-97-0", 556.7, 41.89, 183.35, 0.001, "Leppert2020b, alkane, alkanes", 7.879073502414208e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C23", "638-67-5", 566.26, 42.25, 188.99, 0.001, "Leppert2020b, alkane, alkanes", 7.693149436827684e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C24", "646-31-1", 575.2, 42.21, 188.53, 0.001, "Leppert2020b, alkane, alkanes", 7.518755251713027e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C25", "629-99-2", 583.8199999999999, 42.26, 189.51, 0.001, "Leppert2020b, alkane, alkanes", 7.354754525382887e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C26", "630-1-3", 593.5699999999999, 44.16, 216.77, 0.001, "Leppert2020b, alkane", 7.200161658208628e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C27", "593-49-7", 599.77, 41.9, 184.17, 0.001, "Leppert2020b, alkane, alkanes", 7.054117055654164e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C28", "630-2-4", 607.3399999999999, 41.82, 183.91, 0.001, "Leppert2020b, alkane", 6.915867131183108e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C29", "630-3-5", 614.55, 41.67, 183.07, 0.001, "Leppert2020b, alkane", 6.784748059430345e-5, 0.0, 0.0), GasChromatographySimulator.Substance("C30", "638-68-6", 621.54, 41.57, 183.28, 0.001, "Leppert2020b, alkane, alkanes", 6.660172475097402e-5, 0.0, 0.0)], GasChromatographySimulator.Options(OwrenZen5(), 1.0e-6, 0.001, "inlet", true, false, "Blumberg", "Pressure"))

The temperature program and the pressure/flow program can be plotted:

p_flow_tg = GasChromatographySimulator.plot_flow(par_tg)
p_press_tg = GasChromatographySimulator.plot_pressure(par_tg)
p_temp_tg = GasChromatographySimulator.plot_temperature(par_tg)
l = @layout([a{0.65w} [b; c]])
p_TpF_tg = plot(p_temp_tg, p_press_tg, p_flow_tg, layout=l)

And the simulation is run:

peaklist_tg, sol_tg = GasChromatographySimulator.simulate(par_tg)
peaklist_tg

22 rows × 9 columns

NametRτRTRσRuRkRResΔs
StringFloat64Float64Float64Float64Float64Float64Float64Float64
1C914.97980.04929875.48210.01845680.3743922.2651422.318189.7806
2C1018.87440.037953696.4020.01453970.3830922.0846720.29281.2319
3C1121.81240.0344387111.8910.01208740.3509832.2804918.275473.112
4C1224.27890.0330431125.3020.01044720.3161692.5720516.626266.5048
5C1326.47750.0330775136.9860.009284110.2806772.9616615.324761.3002
6C1428.52190.0336235147.9580.008435640.2508853.374614.237656.9528
7C1530.45890.0344016158.1520.007746710.2251853.8222713.200952.8076
8C1632.30360.0354683168.00.007270810.2049944.2479612.435449.7431
9C1734.08560.0361809177.5720.006824570.1886244.6565111.647246.5915
10C1835.79450.0371806186.6520.006490240.174565.0684611.00844.0348
11C1937.45430.0382118195.410.006218590.162745.4730710.409741.6411
12C2039.06570.0391839204.0390.006024910.153765.82559.8218939.2898
13C2140.62570.0402336212.240.005864680.1457666.172379.4248337.7006
14C2242.1580.0410552220.5360.005760080.1403016.436378.9205135.6838
15C2343.64110.0420741228.4680.005695150.135366.693188.6048134.421
16C2445.10730.0431222236.0730.005620640.1303426.965228.2223932.8898
17C2546.53160.0434899243.9140.005573220.128157.089737.9160531.6659
18C2647.92640.0446066251.2990.005613670.1258497.241657.5721730.2892
19C2749.28680.045225258.4340.00556680.1230917.41937.3456729.383
20C2850.6230.0457294265.6870.005596760.1223887.472357.0997828.3995
21C2951.93030.0463357272.7110.0056480.1218937.514096.8846927.5395
22C3053.21820.0471955279.4120.005711220.1210127.57716NaNNaN

The file Leppert2020b_measured_RT_med_gradient.csv contains the retention times and peak widths (as standard deviations) from the measured chromatogram.

measurement_tg = DataFrame(CSV.File("../../data/measurements/Leppert2020b_measured_RT_med_gradient.csv", header=1, silencewarnings=true))
measurement_tg[!, 3] = measurement_tg[!, 3] ./ 1000.0 # conversion from ms -> s
rename!(measurement_tg, [:Name, :tR, :τR])

22 rows × 3 columns

NametRτR
String3Float64Float64
1C914.76830.0669811
2C1018.22830.0565467
3C1121.02830.0526464
4C1223.50830.0609966
5C1325.76830.0581621
6C1427.88830.0571819
7C1529.88830.0574451
8C1631.80830.0573303
9C1733.66830.0598955
10C1835.46830.0616608
11C1937.22830.0638519
12C2038.90830.0636418
13C2140.54830.0664711
14C2242.12830.068909
15C2343.66830.0718497
16C2445.14830.0726997
17C2546.58830.0772066
18C2648.02830.0816995
19C2749.42830.0847638
20C2850.82830.0920254
21C2952.20830.0987833
22C3053.54830.110653

The simulated and measured separations can be compared by comparing the peak lists:

compare_tg = GasChromatographySimulator.compare_peaklist(measurement_tg, peaklist_tg)

22 rows × 9 columns

NametR1tR2ΔtRrel_tRτR1τR2ΔτRrel_τR
String3Float64Float64Float64Float64Float64Float64Float64Float64
1C914.768314.9798-0.211549-1.432460.06698110.0492980.017683126.4001
2C1018.228318.8744-0.646118-3.544590.05654670.03795360.018593132.881
3C1121.028321.8124-0.784087-3.728730.05264640.03443870.018207734.5849
4C1223.508324.2789-0.77061-3.278040.06099660.03304310.027953545.828
5C1325.768326.4775-0.709279-2.752530.05816210.03307750.025084643.1288
6C1427.888328.5219-0.633627-2.272020.05718190.03362350.023558441.199
7C1529.888330.4589-0.570654-1.909290.05744510.03440160.023043540.114
8C1631.808332.3036-0.495331-1.557240.05733030.03546830.02186238.1333
9C1733.668334.0856-0.41731-1.239480.05989550.03618090.023714639.5933
10C1835.468335.7945-0.326207-0.9197140.06166080.03718060.024480239.7014
11C1937.228337.4543-0.226058-0.6072210.06385190.03821180.025640140.1556
12C2038.908339.0657-0.157394-0.4045260.06364180.03918390.024457938.4306
13C2140.548340.6257-0.077454-0.1910170.06647110.04023360.026237539.472
14C2242.128342.158-0.0297202-0.0705470.0689090.04105520.027853940.4212
15C2343.668343.64110.02716960.06221810.07184970.04207410.029775641.4415
16C2445.148345.10730.04097380.0907540.07269970.04312220.029577540.6845
17C2546.588346.53160.05665810.1216140.07720660.04348990.033716743.6708
18C2648.028347.92640.1019060.2121790.08169950.04460660.037092945.4016
19C2749.428349.28680.1414770.2862260.08476380.0452250.039538946.6459
20C2850.828350.6230.2052240.403760.09202540.04572940.046295950.3078
21C2952.208351.93030.277940.5323670.09878330.04633570.052447553.0935
22C3053.548353.21820.3300740.6164040.1106530.04719550.063457857.3483

or by comparing the chromatograms:

chrom_tg = DataFrame(CSV.File("../../data/measurements/Leppert2020b_measured_Chrom_med_gradient_x90.csv", header=1, silencewarnings=true))
p_chrom_tg, t_, chrom_ = GasChromatographySimulator.plot_chromatogram(peaklist_tg, (0.0, 55.0); annotation=false, number=true, mirror=true, offset=0.0)
plot!(p_chrom_tg, chrom_tg[!,1], chrom_tg[!,2].*8e-5)
ylims!(-13,13)
xlims!(0.0,55.0)
p_chrom_tg